package com.dxj1992.utils;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dxj1992.entity.UserAsset;
import com.dxj1992.entity.UserAssetFlow;
import com.dxj1992.service.IUserAssetFlowService;
import com.dxj1992.service.IUserAssetService;
import com.dxj1992.utils.spring.SpringUtils;
import lombok.Data;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;

@Data
public class Asset {
    private Long userId;
    private Long type;
    private Long subType;
    private String tradeNo;
    private Double amount;
    private String remark;
    private UserAsset userAsset;
    private IUserAssetService iUserAssetService = SpringUtils.getBean("IUserAssetService");
    private IUserAssetFlowService iUserAssetFlowService = SpringUtils.getBean("IUserAssetFlowService");

    public Asset() {
    }

    public Asset(Long userId, Long type, String tradeNo, Double amount, String remark) {

        String substring = type.toString().substring(0, 1);
        this.userId = userId;
        this.type = Long.valueOf(substring);
        this.subType = type;
        this.tradeNo = tradeNo;
        this.amount = amount;
        this.remark = remark;

        this.userAsset = iUserAssetService.getOne(Wrappers.<UserAsset>lambdaQuery().eq(UserAsset::getUserId, userId));
        if (StringUtils.isEmpty(this.userAsset)) {
            iUserAssetService.save(new UserAsset(userId.intValue()));
            this.userAsset = this.iUserAssetService.getOne(Wrappers.<UserAsset>lambdaQuery().eq(UserAsset::getUserId, userId));
        }
    }

    /**
     * 支出
     *
     * @throws Exception
     */
    public void expend(){

        try {
            if (this.getType() != 1) {
                throw new Exception("支出类型错误");
            }
            // 检测余额是否够本次支出
            if (this.userAsset.getBalance().doubleValue() < this.getAmount()) {
                throw new Exception("您的余额不足");
            }
            // 写流水
            this.flow(
                    BigDecimal.valueOf(Arith.sub(this.userAsset.getBalance().doubleValue(), this.getAmount())),
                    this.userAsset.getFrozen(),
                    this.userAsset.getTotalRecharge(),
                    this.userAsset.getTotalWithdraw(),
                    this.userAsset.getTotalRefund(),
                    this.userAsset.getTotalConsume(),
                    BigDecimal.valueOf(Arith.add(this.userAsset.getTotalExpend().doubleValue(), this.getAmount())),
                    this.userAsset.getTotalIncome()
            );
            // 更新卡平台余额、入库金额
            this.userAsset.setBalance(BigDecimal.valueOf(Arith.sub(this.userAsset.getBalance().doubleValue(), this.getAmount())));
            this.userAsset.setTotalExpend(BigDecimal.valueOf(Arith.add(this.userAsset.getTotalExpend().doubleValue(), this.getAmount())));
            iUserAssetService.updateById(this.userAsset);
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    /**
     * 收入
     */
    public void income() {
        try {
            if (this.getType() != 2) {
                throw new Exception("收入类型错误");
            }
            // 写流水
            this.flow(
                    BigDecimal.valueOf(Arith.add(this.userAsset.getBalance().doubleValue(), this.getAmount())),
                    userAsset.getFrozen(),
                    this.userAsset.getTotalRecharge(),
                    this.userAsset.getTotalWithdraw(),
                    this.userAsset.getTotalRefund(),
                    BigDecimal.valueOf(Arith.add(this.userAsset.getTotalConsume().doubleValue(), this.getAmount())),
                    this.userAsset.getTotalExpend(),
                    this.userAsset.getTotalIncome()
            );
            // 更新卡平台余额、入库金额
            this.userAsset.setBalance(BigDecimal.valueOf(Arith.add(this.userAsset.getBalance().doubleValue(), this.getAmount())));
            this.userAsset.setTotalConsume(BigDecimal.valueOf(Arith.add(this.userAsset.getTotalConsume().doubleValue(), this.getAmount())));
            this.iUserAssetService.updateById(this.userAsset);
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

    /**
     * 写流水
     *
     * @param balance
     * @param frozen
     * @param totalRecharge
     * @param totalWithdraw
     * @param totalRefund
     * @param totalConsume
     * @param totalExpend
     * @param totalIncome
     */
    private void flow(BigDecimal balance, BigDecimal frozen, BigDecimal totalRecharge, BigDecimal totalWithdraw, BigDecimal totalRefund, BigDecimal totalConsume, BigDecimal totalExpend, BigDecimal totalIncome) {
        UserAssetFlow userAssetFlow = new UserAssetFlow();
        userAssetFlow.setUserId(this.getUserId().intValue());
        userAssetFlow.setType(this.getType().intValue());
        userAssetFlow.setSubType(this.getSubType().intValue());
        userAssetFlow.setTradeNo(this.getTradeNo());
        userAssetFlow.setAmount(BigDecimal.valueOf(this.getAmount()));
        userAssetFlow.setBalance(balance);
        userAssetFlow.setFrozen(frozen);
        userAssetFlow.setTotalRecharge(totalRecharge);
        userAssetFlow.setTotalWithdraw(totalWithdraw);
        userAssetFlow.setTotalConsume(totalConsume);
        userAssetFlow.setTotalExpend(totalExpend);
        userAssetFlow.setTotalIncome(totalIncome);
        userAssetFlow.setTotalRefund(totalRefund);
        userAssetFlow.setRemark(this.getRemark());
        userAssetFlow.setDate(LocalDate.now());
        userAssetFlow.setCreatedAt(LocalDateTime.now());
        userAssetFlow.setUpdatedAt(LocalDateTime.now());

        Long[] type = new Long[]{1L};
        if (Arrays.asList(type).contains(this.getType())) {
            userAssetFlow.setAmount(BigDecimal.valueOf(this.getAmount()).negate());
        }
        this.iUserAssetFlowService.save(userAssetFlow);
    }

}
